- Created on 2014-10
教材:《汇编语言》(第二版)王爽 著 清华大学出版社
章九、转移指令的原理
可以修改IP,或同时修改CS和IP的指令统称为转移指令。
8086CPU的转移行为有以下几类:
(1)只修改IP时,称为段内转移。如,jmp ax。
(2)同时修改CS和IP时,称为段间转移。如,jmp 1000:0。
由于转移指令对IP的修改范围不同,段内转移又分为:
(1)短转移:IP的修改范围为-128~127。
(2)近转移:IP的修改范围为-32768~32767。(2的15次方=32768)
8086CPU的转移指令分为以下几类:
(1)无条件转移指令 (如:jmp)
(2)条件转移指令
(3)循环指令(如:loop)
(4)过程
(5)中断
9.1 操作符offset
offset是由编译器处理的符号,功能是取得标号的偏移地址。如:
start: mov ax, offset start
extra:nop指令
nop指令即“空指令”,在x86的CPU中机器码为0x90(144)。
执行到NOP指令时,CPU什么也不做,
仅仅当做一个指令执行过去并继续执行NOP后面的一条指令。
所以NOP指令自然也会占用执行一个指令的CPU时间片,其机器码占 1 byte。
常用于程序延时或精确计时,不过在较快的CPU上不明显。
主要作用:
(1)字节填充对齐
(2)精确延时和计时
(3)破解程序的call验证
(4)等待其他设备执行完毕
(5)清除由上一个算术逻辑指令设置的flag位
(6)辅助jmp、call等指令
9.2 jmp 指令
它需要给出两种信息:
(1)转移的目的地址;
(2)转移的距离(段间转移、段内短转移、段内近转移)。
9.3 依据位移进行转移的jmp指令
CPU执行jmp short指令的时候,并不需要转移的目的地址,而是要转移的位移,
就是执行此指令时的ip,到所要转移到的指令的内存地址的距离。
例:jmp short start
段内短转移: jmp short 标号(跳转到标号处执行指令)
功能为:( IP ) = ( IP ) + 8位位移
(1)8位位移 = 标号处的地址 - jmp short 指令后的第一个字节的地址;
(标号,即如,之前常用start)
(2)short指明此处的位移为8位位移
(3)8位位移范围:-128~127;用补码表示。
(4)8位位移由编译程序在编译时算出。
段内近转移:jmp near ptr 标号(跳转到标号处执行指令)
功能为:(IP)=(IP)+ 16位位移
(1)(2)(4)等的特征,类同上
(3)范围为-32768~32767,…
9.4 转移的目的地址在指令中的jmp指令
(CS)= 标号所在段的段地址;
(IP)= 标号所在段的偏移地址
far ptr指明用标号的段地址和偏移地址修改CS和IP。
例:
-u
...
00BD:0005 EB03 JMP 0008 // jmp short 标号,用相对位移
00BD:0006 EA0B01BD0B JMP 0BBD:010B // jmp far ptr 标号,用内存地址
... // 上一条指令的低地址存偏移地址,高地址存段地址
9.5 转移地址在寄存器中的jmp指令
格式:jmp 16位reg
功能:(IP) = (16位reg),根据16位reg修改IP寄存器(reg)的内容
例子:jmp ax
含义:mov IP, ax
9.6 转移地址在内存中的jmp指令
有两种类型:
(1)jmp word ptr 内存单元地址(段内转移)
内存单元地址处,存放着一个word,是转移的目的偏移地址。
例:jmp word ptr ds:[0]
(2)jmp dword ptr 内存单元地址(段间转移)
内存单元地址处,存放着一个dword(两个word),
低地址存偏移地址,高地址存段地址。
检测点9.1:
(1)要使jmp指令之后,CS:IP指向程序的第一条指令,
该在data段定义什么数据
9.9 根据位移进行转移的意义
因为这样做,程序无论放在内存哪里,都可以根据相对位移去执行jmp;
一旦写死了跳转地址,那么程序就必须放在指定位置才能正常执行了!
9.10 编译器对转移位移的超界检测
根据位移进行转移的指令,它们转移范围有限制,如-128~127。
如果源程序中出现了转移范围超界的问题,编译器会报错。例:
start: jmp short s
(1)只修改IP时,称为段内转移。如,jmp ax。
(2)同时修改CS和IP时,称为段间转移。如,jmp 1000:0。
(1)短转移:IP的修改范围为-128~127。
(2)近转移:IP的修改范围为-32768~32767。(2的15次方=32768)
(1)无条件转移指令 (如:jmp)
(2)条件转移指令
(3)循环指令(如:loop)
(4)过程
(5)中断
offset是由编译器处理的符号,功能是取得标号的偏移地址。如:
start: mov ax, offset start
nop指令即“空指令”,在x86的CPU中机器码为0x90(144)。
执行到NOP指令时,CPU什么也不做,
仅仅当做一个指令执行过去并继续执行NOP后面的一条指令。
所以NOP指令自然也会占用执行一个指令的CPU时间片,其机器码占 1 byte。
常用于程序延时或精确计时,不过在较快的CPU上不明显。
主要作用:
(1)字节填充对齐
(2)精确延时和计时
(3)破解程序的call验证
(4)等待其他设备执行完毕
(5)清除由上一个算术逻辑指令设置的flag位
(6)辅助jmp、call等指令
它需要给出两种信息:
(1)转移的目的地址;
(2)转移的距离(段间转移、段内短转移、段内近转移)。
CPU执行jmp short指令的时候,并不需要转移的目的地址,而是要转移的位移,
就是执行此指令时的ip,到所要转移到的指令的内存地址的距离。
例:jmp short start
功能为:( IP ) = ( IP ) + 8位位移
(1)8位位移 = 标号处的地址 - jmp short 指令后的第一个字节的地址;
(标号,即如,之前常用start)
(2)short指明此处的位移为8位位移
(3)8位位移范围:-128~127;用补码表示。
(4)8位位移由编译程序在编译时算出。
功能为:(IP)=(IP)+ 16位位移
(1)(2)(4)等的特征,类同上
(3)范围为-32768~32767,…
(CS)= 标号所在段的段地址;
(IP)= 标号所在段的偏移地址
far ptr指明用标号的段地址和偏移地址修改CS和IP。
-u
...
00BD:0005 EB03 JMP 0008 // jmp short 标号,用相对位移
00BD:0006 EA0B01BD0B JMP 0BBD:010B // jmp far ptr 标号,用内存地址
... // 上一条指令的低地址存偏移地址,高地址存段地址
格式:jmp 16位reg
功能:(IP) = (16位reg),根据16位reg修改IP寄存器(reg)的内容
例子:jmp ax
含义:mov IP, ax
有两种类型:
(1)jmp word ptr 内存单元地址(段内转移)
内存单元地址处,存放着一个word,是转移的目的偏移地址。
例:jmp word ptr ds:[0]
(2)jmp dword ptr 内存单元地址(段间转移)
内存单元地址处,存放着一个dword(两个word),
低地址存偏移地址,高地址存段地址。
(1)要使jmp指令之后,CS:IP指向程序的第一条指令,
该在data段定义什么数据
assume cs:code
data segment
db 0 // 在测试时,此处是078A:0000
data ends
code segment
start: mov ax, data // 在测试时,此处是078B:0010 = 078A:0000,因为078BH * 10H = 078AH * 10H + 10H
mov ds, ax
mov bx, 0
jmp word ptr 1[bx]
mov ax, 4c00h
int 21h
code ends
end start
(2)要使jmp指令之后,CS:IP指向程序的第一条指令,
该在MOV [BX]和MOV 2[BX]处补全些什么。
assume cs:code
data segment
dd 12345678H
data ends
code segment
start: mov ax, data
mov ds, ax
mov bx, 0
mov word ptr [bx], 0
mov word ptr 2[bx], cs
jmp dword ptr ds:[0]
mov ax, 4c00h
int 21h
code ends
end start
检测点9.2:补全程序(补全位置为s标号紧接着的四行),
利用jcxz指令,实现在内存2000H段中寻找第一个值为0的字节。
assume cs:code
code segment
start: mov ax, 2000H
mov ds, ax
mov bx, 0
s: mov ch, 0
mov cl, [bx]
jcxz ok
inc bx
jmp short s
ok: mov dx, bx
mov ax, 4c00h
int 21h
code ends
end start
9.7 jcxz指令: 有条件转移指令。
所有有条件转移指令,都是短转移,
在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都是-128~127。
指令格式:jcxz 标号
功能:当(cx)= 0时,(IP)=(IP)+ 8位位移。
其它:类同jmp short。
9.8 loop指令:循环指令,所有的循环指令都是短转移,
其它说明类同上。
指令格式:loop 标号
功能:
(1)(cx)=(cx)- 1
(2)当(cx)!= 0时,(IP)=(IP)+ 8位位移。
其它:类同jmp short。
dec指令:与inc指令相反,dec bx功能为(bx) = (bx) - 1
检测点9.3:补全程序(加粗的那一行),
利用loop指令,实现在内存2000H段中寻找第一个值为0的字节。
assume cs:code所有有条件转移指令,都是短转移,
在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都是-128~127。
指令格式:jcxz 标号
功能:当(cx)= 0时,(IP)=(IP)+ 8位位移。
其它:类同jmp short。
其它说明类同上。
指令格式:loop 标号
功能:
(1)(cx)=(cx)- 1
(2)当(cx)!= 0时,(IP)=(IP)+ 8位位移。
其它:类同jmp short。
利用loop指令,实现在内存2000H段中寻找第一个值为0的字节。
code segment
start: mov ax, 2000H
mov ds, ax
mov bx, 0
s: mov ch, 0
mov cl, [bx]
inc cx
inc bx
loop s
ok: dec bx
mov dx, bx
mov ax, 4c00h
int 21h
code ends
end start
因为这样做,程序无论放在内存哪里,都可以根据相对位移去执行jmp;
一旦写死了跳转地址,那么程序就必须放在指定位置才能正常执行了!
根据位移进行转移的指令,它们转移范围有限制,如-128~127。
如果源程序中出现了转移范围超界的问题,编译器会报错。例:
start: jmp short s
db 128 dup (0)
s: mov ax, 0ffffh
实验8 分析一个奇怪的程序
assume cs:code
code segment
mov ax, 4c00h
int 21h
start: mov ax, 0
s: nop
nop
mov di, offset s
mov si, offset s2
mov ax, cs:[si]
mov cs:[di], ax
s0: jmp short s
s1: mov ax, 0
int 21h
mov ax, 0
s2: jmp short s1 // jmp short使用的是相对位移。二进制编码为:EBF6。F6表示-10的位移。
nop // 当上一句指令被拷贝到标号s处时,意义就不同了,变成了跳到cs:[0]处了!
code ends // 8位位移 = 标号处的地址 - jmp short 指令后的第一个字节的地址
end start
实验9 根据材料编程
材料比较繁多,最好阅读原书题目。可以增进知识。(后来,下文增加原书材料的相片)
任务:在屏幕中间分别显示绿色、绿底红色、白底蓝色的字符串‘welcome to masm!’。
assume cs:code, ds:data, ss:stack
data segment
db 'welcome to masm!'
db 27h, 42h, 01h, 13 dup (0)
data ends
stack segment
dw 8 dup (0)
stack ends
code segment
start: mov ax, stack
mov ss, ax
mov sp, 16
mov ax, data
mov ds, ax
mov ax, 0b800h
mov es, ax
mov bx, 6e0h ;1760bytes
mov si, 0
mov cx, 3
s: push cx
mov di, 0
mov bp, 0
mov cx, 16
s0: mov al, ds:[bp]
mov es:40h[di][bx], al
mov al, ds:10h[si]
mov es:41h[di][bx], al
inc di
inc di
inc bp
loop s0
pop cx
add bx, 0a0h
inc si
loop s
mov ax, 4c00h
int 21h
code ends
end start
data segment
db 'welcome to masm!'
db 27h, 42h, 01h, 13 dup (0)
data ends
stack segment
dw 8 dup (0)
stack ends
code segment
start: mov ax, stack
mov ss, ax
mov sp, 16
mov ax, data
mov ds, ax
mov ax, 0b800h
mov es, ax
mov bx, 6e0h ;1760bytes
mov si, 0
mov cx, 3
s: push cx
mov di, 0
mov bp, 0
mov cx, 16
s0: mov al, ds:[bp]
mov es:40h[di][bx], al
mov al, ds:10h[si]
mov es:41h[di][bx], al
inc di
inc di
inc bp
loop s0
pop cx
add bx, 0a0h
inc si
loop s
mov ax, 4c00h
int 21h
code ends
end start
Att - 汇编语言第九章实验9.asm


Show Comments